bitkeeper revision 1.500 (3f86be35Q1ywfgRyq1VKkvPUP_JZ_A)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 10 Oct 2003 14:12:05 +0000 (14:12 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 10 Oct 2003 14:12:05 +0000 (14:12 +0000)
xi_vif_params.c:
  new file
dev.c, vif.h, network.h, network.c, xen_read_console.c, Makefile:
  Credit-based network scheduling.

.rootkeys
tools/internal/Makefile
tools/internal/xi_vif_params.c [new file with mode: 0644]
tools/misc/xen_read_console.c
xen/common/network.c
xen/include/hypervisor-ifs/network.h
xen/include/xeno/vif.h
xen/net/dev.c

index e212512e4bf8d3ffc181cbc4db2554e9dd061344..de66e17a7dc0541a2efcb266308cdef4e6d0cc08 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3eb781fd8oRfPgH7qTh7xvgmwD6NgA tools/internal/xi_start.c
 3eb781fd0Eo9K1jEFCSAVzO51i_ngg tools/internal/xi_stop.c
 3f108ae2to5nHRRXfvUK7oxgjcW_yA tools/internal/xi_usage.c
+3f86be322bd0h9jG3krZFOUgCDoxZg tools/internal/xi_vif_params.c
 3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit
 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
index ac76ebbb7c4551bda557a5933a7cda2267048684..3fb527fd07eb68efa9de009d9f0e8ef1bf161deb 100644 (file)
@@ -9,7 +9,7 @@ OBJS     = $(patsubst %.c,%.o,$(SRCS))
 
 TARGETS  = xi_create xi_start xi_stop xi_destroy xi_build 
 TARGETS += xi_phys_grant xi_phys_revoke xi_phys_probe xi_list 
-TARGETS += xi_sched_global xi_sched_domain xi_usage
+TARGETS += xi_sched_global xi_sched_domain xi_usage xi_vif_params
 INSTALL  = $(TARGETS) xi_vifinit xi_helper
 
 all: $(TARGETS)
diff --git a/tools/internal/xi_vif_params.c b/tools/internal/xi_vif_params.c
new file mode 100644 (file)
index 0000000..e954253
--- /dev/null
@@ -0,0 +1,86 @@
+
+#include "hypervisor-ifs/dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+static char *argv0 = "internal_domain_vif_params";
+
+int main(int argc, char **argv)
+{
+    network_op_t  netop;
+    int           domain, vif;
+    unsigned long credit_bytes, credit_usec;
+    
+    if ( argv[0] != NULL ) 
+        argv0 = argv[0];
+
+    if ( (argc != 3) && (argc != 5) ) 
+    {
+        fprintf(stderr, "Usage: %s <domain-id> <vif-id> "
+                "[<credit-bytes> <credit-usec>]\n", argv0);
+        fprintf(stderr, "Specify <credit usec> == 0 to disable scheduling\n");
+        return 1;
+    }
+
+    domain = atol(argv[1]);
+    vif    = atol(argv[2]);
+
+    if ( argc == 5 )
+    {
+        credit_bytes = atol(argv[3]);
+        credit_usec  = atol(argv[4]);
+
+        netop.cmd = NETWORK_OP_VIFSETPARAMS;
+        netop.u.vif_setparams.domain       = domain;
+        netop.u.vif_setparams.vif          = vif;
+        netop.u.vif_setparams.credit_bytes = credit_bytes;
+        netop.u.vif_setparams.credit_usec  = credit_usec;
+        if ( do_network_op(&netop) < 0 )
+            return 1;
+
+        if ( credit_usec != 0 )
+        {
+            printf("Set scheduling to %lu bytes every"
+                   " %lu usecs (%2.2f Mbps)\n",
+                   credit_bytes, credit_usec,
+                   ((float)credit_bytes/(1024.0*1024.0/8.0)) /
+                   ((float)credit_usec/1000000.0));
+        }
+        else
+        {
+            printf("Disabled rate limiting for vif\n");
+        }
+    }
+    else
+    {
+        netop.cmd = NETWORK_OP_VIFGETINFO;
+        netop.u.vif_getinfo.domain = domain;
+        netop.u.vif_getinfo.vif    = vif;
+        if ( do_network_op(&netop) < 0 )
+            return 1;
+        
+        printf("%lld bytes transmitted\n"
+               "%lld packets transmitted\n"
+               "%lld bytes received\n"
+               "%lld packets received\n",
+               netop.u.vif_getinfo.total_bytes_sent,
+               netop.u.vif_getinfo.total_packets_sent,
+               netop.u.vif_getinfo.total_bytes_received,
+               netop.u.vif_getinfo.total_packets_received);
+
+        if ( netop.u.vif_getinfo.credit_usec != 0 )
+        {
+            printf("Scheduling: %lu bytes every %lu usecs (%2.2f Mbps)\n",
+               netop.u.vif_getinfo.credit_bytes,
+                   netop.u.vif_getinfo.credit_usec,
+               ((float)netop.u.vif_getinfo.credit_bytes/(1024.0*1024.0/8.0)) /
+               ((float)netop.u.vif_getinfo.credit_usec/1000000.0));
+        }
+        else
+        {
+            printf("Scheduling: no rate limit\n");
+        }
+    }
+
+    return 0;
+}
index 43879e5035373bc2dd8fdea2241c924776f84599..766d24f6f38c053502f8a4ea9e4770d5bc67b186 100644 (file)
@@ -11,7 +11,7 @@
 
 int main(void)
 {
-    unsigned char buf[208], abuf[32];
+    unsigned char buf[208];
     struct sockaddr_in addr, from;
     int fromlen = sizeof(from);
     int len, fd = socket(PF_INET, SOCK_DGRAM, 0);
@@ -37,6 +37,7 @@ int main(void)
             >= 0 )
     {
 #if 0
+        unsigned char abuf[32];
         printf("%d-byte message from %s:%d --\n", len,
                inet_ntop(AF_INET, &from.sin_addr, abuf, sizeof(abuf)),
                ntohs(from.sin_port));
index 5a8fd564741ef78731d1f8afcb70251524b23e85..d51195059e17aa8d20c65f6dd2fbaaf638c18f20 100644 (file)
@@ -105,6 +105,10 @@ net_vif_t *create_net_vif(int domain)
     spin_lock_init(&new_vif->rx_lock);
     spin_lock_init(&new_vif->tx_lock);
 
+    new_vif->credit_bytes = new_vif->remaining_credit = ~0UL;
+    new_vif->credit_usec  = 0UL;
+    init_ac_timer(&new_vif->credit_timeout, 0);
+
     if ( (p->domain == 0) && (dom_vif_idx == 0) )
     {
         /*
@@ -246,35 +250,46 @@ int vif_query(vif_query_t *vq)
  */
 int vif_getinfo(vif_getinfo_t *info)
 {
-    struct task_struct *p;
     net_vif_t *vif;
 
-    info->total_bytes_sent =
-    info->total_bytes_received =
-    info->total_packets_sent =
-    info->total_packets_received = -1;
-
-    if ( !(p = find_domain_by_id(info->domain)) )
-        return -ENOSYS;
-
-    vif = p->net_vif_list[info->vif];
-
+    vif = find_vif_by_id((info->domain << VIF_DOMAIN_SHIFT) | info->vif);
     if ( vif == NULL )
-    {
-        put_task_struct(p);
-        return -ENOSYS;
-    }
+        return -ESRCH;
 
     info->total_bytes_sent              = vif->total_bytes_sent;
     info->total_bytes_received          = vif->total_bytes_received;
     info->total_packets_sent            = vif->total_packets_sent;
     info->total_packets_received        = vif->total_packets_received;
 
-    put_task_struct(p);
+    info->credit_bytes = vif->credit_bytes;
+    info->credit_usec  = vif->credit_usec;
+
+    put_vif(vif);
 
     return 0;
 }
 
+
+int vif_setparams(vif_setparams_t *params)
+{
+    net_vif_t *vif;
+
+    vif = find_vif_by_id((params->domain << VIF_DOMAIN_SHIFT) | params->vif);
+    if ( vif == NULL )
+        return -ESRCH;
+
+    /* Turning off rate limiting? */
+    if ( params->credit_usec == 0 )
+        params->credit_bytes = ~0UL;
+
+    vif->credit_bytes = vif->remaining_credit = params->credit_bytes;
+    vif->credit_usec  = params->credit_usec;
+
+    put_vif(vif);
+
+    return 0;    
+}
+
         
 /* ----[ Net Rule Functions ]-----------------------------------------------*/
 
@@ -572,6 +587,12 @@ long do_network_op(network_op_t *u_network_op)
     }
     break;
     
+    case NETWORK_OP_VIFSETPARAMS:
+    {
+        ret = vif_setparams(&op.u.vif_setparams);
+    }
+    break;
+    
     default:
         ret = -ENOSYS;
     }
index cd64f4fa730ce7c7479bce881169276b41ceff74..c35f1bab1527f6133caf818ae7459e03bb091094 100644 (file)
@@ -127,13 +127,30 @@ typedef struct vif_getinfo_st
 {
     unsigned int        domain;
     unsigned int        vif;
+
     /* domain & vif are supplied by dom0, the rest are response fields */
     long long           total_bytes_sent;
     long long           total_bytes_received;
     long long           total_packets_sent;
     long long           total_packets_received;
+
+    /* Current scheduling parameters */
+    unsigned long credit_bytes;
+    unsigned long credit_usec;
 } vif_getinfo_t;
 
+/*
+ * Set parameters associated with a VIF. Currently this is only scheduling
+ * parameters --- permit 'credit_bytes' to be transmitted every 'credit_usec'.
+ */
+typedef struct vif_setparams_st
+{
+    unsigned int        domain;
+    unsigned int        vif;
+    unsigned long       credit_bytes;
+    unsigned long       credit_usec;
+} vif_setparams_t;
+
 /* Network trap operations and associated structure. 
  * This presently just handles rule insertion and deletion, but will
  * evenually have code to add and remove interfaces.
@@ -144,6 +161,7 @@ typedef struct vif_getinfo_st
 #define NETWORK_OP_GETRULELIST  2
 #define NETWORK_OP_VIFQUERY     3
 #define NETWORK_OP_VIFGETINFO   4
+#define NETWORK_OP_VIFSETPARAMS 5
 
 typedef struct network_op_st 
 {
@@ -153,6 +171,7 @@ typedef struct network_op_st
         net_rule_t net_rule;
         vif_query_t vif_query;
         vif_getinfo_t vif_getinfo;
+        vif_setparams_t vif_setparams;
     }
     u;
 } network_op_t;
index ee9201011aa227e1a72bfa3f9483359fcda0acbb..f3ee9fa61635ac322e65bc1a956121fdf9fd967d 100644 (file)
@@ -72,6 +72,12 @@ typedef struct net_vif_st {
     long long total_packets_sent;
     long long total_packets_received;
 
+    /* Trasnmit shaping: allow 'credit_bytes' everu 'credit_usec'. */
+    unsigned long   credit_bytes;
+    unsigned long   credit_usec;
+    unsigned long   remaining_credit;
+    struct ac_timer credit_timeout;
+
     /* Miscellaneous private stuff. */
     struct task_struct *domain;
     unsigned int idx; /* index within domain */
index 22b81bcc58371d4a1863aeace784015069dc7c63..2fcf935319189beb7cb7bb6eb01069352bdbb57e 100644 (file)
@@ -1824,6 +1824,18 @@ inline int init_tx_header(net_vif_t *vif, u8 *data,
     return proto;
 }
 
+static void tx_credit_callback(unsigned long data)
+{
+    net_vif_t *vif = (net_vif_t *)data;
+
+    vif->remaining_credit = vif->credit_bytes;
+
+    if ( get_tx_bufs(vif) )
+    {
+        add_to_net_schedule_list_tail(vif);
+        maybe_schedule_tx_action();
+    }    
+}
 
 static int get_tx_bufs(net_vif_t *vif)
 {
@@ -1837,7 +1849,7 @@ static int get_tx_bufs(net_vif_t *vif)
     unsigned short      protocol;
     struct sk_buff     *skb;
     tx_req_entry_t      tx;
-    int                 i, j, ret;
+    int                 i, j, ret = 0;
     unsigned long       flags;
 
     if ( vif->tx_req_cons == shared_idxs->tx_req_prod )
@@ -1845,6 +1857,10 @@ static int get_tx_bufs(net_vif_t *vif)
 
     spin_lock_irqsave(&vif->tx_lock, flags);
 
+    /* Currently waiting for more credit? */
+    if ( vif->remaining_credit == 0 )
+        goto out;
+
     j = vif->tx_prod;
 
     /*
@@ -1868,6 +1884,29 @@ static int get_tx_bufs(net_vif_t *vif)
             continue; 
         }
 
+        /* Credit-based scheduling. */
+        if ( tx.size > vif->remaining_credit )
+        {
+            s_time_t now = NOW(), next_credit = 
+                vif->credit_timeout.expires + MICROSECS(vif->credit_usec);
+            if ( next_credit <= now )
+            {
+                vif->credit_timeout.expires = now;
+                vif->remaining_credit = vif->credit_bytes;
+            }
+            else
+            {
+                vif->remaining_credit = 0;
+                vif->credit_timeout.expires  = next_credit;
+                vif->credit_timeout.data     = (unsigned long)vif;
+                vif->credit_timeout.function = tx_credit_callback;
+                vif->credit_timeout.cpu      = smp_processor_id();
+                add_ac_timer(&vif->credit_timeout);
+                break;
+            }
+        }
+        vif->remaining_credit -= tx.size;
+
         /* No crossing a page boundary as the payload mustn't fragment. */
         if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE ) 
         {
@@ -1966,12 +2005,14 @@ static int get_tx_bufs(net_vif_t *vif)
      */
     smp_mb();
 
-    if ( (vif->tx_req_cons = i) != shared_idxs->tx_req_prod )
+    if ( ((vif->tx_req_cons = i) != shared_idxs->tx_req_prod) &&
+         (vif->remaining_credit != 0) )
         goto again;
 
     if ( (ret = (vif->tx_prod != j)) )
         vif->tx_prod = j;
 
+ out:
     spin_unlock_irqrestore(&vif->tx_lock, flags);
 
     return ret;